/**
 * File: CompraItensMB.java
 * Data: 05.01.2011
 * Objective: Criar a classe managed bean da entidade que representa o Item da Compra.
 *
 * Copyright 2011 S2DZ CORPORATION
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package mbeans;

import controller.CompraHeaderController;
import controller.CompraItensController;
import controller.ContasPagarController;
import controller.ControllerUtil;
import controller.ProdutoController;
import controller.StockController;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import modelo.CompraHeaderModelo;
import modelo.CompraItensModelo;
import modelo.ContasPagarModelo;
import modelo.ProdutoModelo;
import modelo.StockModelo;

/**
 * Managed Bean da entidade que representa o Item da Compra.
 * @author Paulo Ilenga
 */
@ManagedBean
@SessionScoped
public class CompraItensMB implements Serializable
{

    private CompraItensController controller;
    private CompraItensModelo modelo, modeloTemp;
    private CompraItensModelo[] seleccionados;
    private ArrayList<CompraItensModelo> carrinhoCompras;
    private FacesContext context;
    private GregorianCalendar gc;
    private ProdutoController produtoController;
    private CompraHeaderController headerController;
    private CompraHeaderModelo headerModelo, headerModeloTemp;
    private ProdutoModelo produtoModelo;
    private StockModelo stockModelo;
    private StockController stockController;
    private ContasPagarController contasPagarController;
    private ContasPagarModelo contasPagarModelo;

    /** Constructor da classe sem argumentos */
    public CompraItensMB()
    {
        controller = new CompraItensController();
        produtoController = new ProdutoController();
        modelo = new CompraItensModelo();
        modeloTemp = new CompraItensModelo();
        gc = new GregorianCalendar();
        carrinhoCompras = new ArrayList<CompraItensModelo>();
        headerController = new CompraHeaderController();
        headerModelo = new CompraHeaderModelo();
        headerModeloTemp = new CompraHeaderModelo();
        produtoModelo = new ProdutoModelo();
        stockController = new StockController();
        contasPagarController = new ContasPagarController();
    }

//------------------------inicio dos Métodos set e get---------------------------------
    public CompraItensController getController()
    {
        return controller;
    }

    public void setController(CompraItensController controller)
    {
        this.controller = controller;
    }

    public CompraItensModelo getModelo() throws SQLException
    {
        return modelo;
    }

    public void setModelo(CompraItensModelo modelo)
    {
        this.modelo = modelo;
    }

    public CompraItensModelo getModeloTemp()
    {
        //limparMsg();
        return modeloTemp;
    }

    public void setModeloTemp(CompraItensModelo modeloTemp)
    {
        this.modeloTemp = modeloTemp;
    }

    public List<CompraItensModelo> getTodos()
    {
        return controller.getTodos();
    }

    public CompraItensModelo[] getSeleccionados()
    {
        return seleccionados;
    }

    public void setSeleccionados(CompraItensModelo[] seleccionados)
    {
        this.seleccionados = seleccionados;
    }

    public ArrayList<CompraItensModelo> getCarrinhoCompras()
    {
        return carrinhoCompras;
    }

    public void setCarrinhoCompras(ArrayList<CompraItensModelo> carrinhoCompras)
    {
        this.carrinhoCompras = carrinhoCompras;
    }

    public CompraHeaderController getHeaderController()
    {
        return headerController;
    }

    public void setHeaderController(CompraHeaderController headerController)
    {
        this.headerController = headerController;
    }

    public CompraHeaderModelo getHeaderModelo()
    {
        headerModelo.setNumDoc((ControllerUtil.getMaxId("tbl_compra_header") + 1) + "/" + gc.get(GregorianCalendar.YEAR));
        headerModelo.setDataRegisto(new Date());
        return headerModelo;
    }

    public void setHeaderModelo(CompraHeaderModelo headerModelo)
    {
        this.headerModelo = headerModelo;
    }

    public ProdutoModelo getProdutoModelo()
    {
        return produtoModelo;
    }

    public void setProdutoModelo(ProdutoModelo produtoModelo)
    {
        this.produtoModelo = produtoModelo;
    }

    public CompraHeaderModelo getHeaderModeloTemp()
    {
        return headerModeloTemp;
    }

    public void setHeaderModeloTemp(CompraHeaderModelo headerModeloTemp)
    {
        this.headerModeloTemp = headerModeloTemp;
    }

    public String getHora()
    {
        return "" + gc.get(GregorianCalendar.HOUR_OF_DAY) + ":" + gc.get(GregorianCalendar.MINUTE);
    }

    //-----------------------fim dos métodos set e get------------------------------
    public List<ProdutoModelo> complete(String query)
    {
        List<ProdutoModelo> list = new ArrayList<ProdutoModelo>();

        for (ProdutoModelo item : produtoController.getTodos(false))
        {
            if (item.getDescricao().startsWith(query))
            {
                list.add(item);
            }
        }

        return list;
    }

    /**
     * Adiciona um item na carro de compra.
     * @param event o e evento gerado.
     */
    public void addItemCarrinhoCompra(ActionEvent event)
    {
        if(modelo != null & produtoModelo != null)
        {
            modelo.setIdProduto(produtoModelo.getId());
            modelo.setProduto(produtoModelo.getDescricao());
        }

        if (modelo.getIdProduto() != 0)
        {
            if (modelo.getPreco() != 0)
            {
                if (modelo.getImposto() != 0)
                {
                    if (modelo.getQuatidade() != 0)
                    {
                        carrinhoCompras.add(modelo);
                        this.produtoModelo = new ProdutoModelo();
                    } else
                    {
                        context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Informar a quantidade!"));
                    }
                } else
                {
                    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Informar o Valor do Imposto"));
                }

            } else
            {
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Informar o Preço"));
            }
        } else
        {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Seleccionar o Produto!"));
        }

        modelo = new CompraItensModelo();
    }

    public String loadItensCompra()
    {
        this.carrinhoCompras = (ArrayList<CompraItensModelo>) controller.getItensDocumento("" + headerModeloTemp.getId());

        return "compraEditarItens";
    }

    /**
     * Metodo que permite estornar um documento.
     * @param event o e evento gerado.
     */
    public void estornarDocumento(ActionEvent event)
    {
        context = FacesContext.getCurrentInstance();

        if (estornarItemsDoc())
        {
            if (headerController.eliminar(headerModeloTemp.getId(), "tbl_compra_header"))
            {
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "GCBoutique", "Documento estornado com sucesso!"));
            }
        } else
        {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "GCBoutique", "Erro N.º SG001: Ao Estornar Itens! Consulte o Suporte"));
        }
    }

    /**
     * Remove um item no carro de compra
     * @param event o evento gerado pelo utilizador
     */
    public void delItemCarrinhoCompra(ActionEvent event)
    {
        if (!carrinhoComprasVaziu())
        {
            for ( Iterator<CompraItensModelo> itemIterator = carrinhoCompras.iterator(); itemIterator.hasNext();)
            {
                CompraItensModelo item = itemIterator.next();

                if (item.getId() == modeloTemp.getId())
                {
                    this.carrinhoCompras.remove(item);
                }
            }
        }

        modeloTemp = new CompraItensModelo();
    }

    /**
     * Retorna o total geral do documento.
     * @return o valor total do documento.
     */
    public float getTotalGeral()
    {
        float total = 0;

        for (CompraItensModelo item : carrinhoCompras)
        {
            total = total + item.getTotal();
        }

        return total;
    }

    /**
     * Método salvar da classe
     */
    public void salvar()
    {
        context = FacesContext.getCurrentInstance();

        if (!headerModelo.getFormaPagamento().equalsIgnoreCase("Seleccionar..."))
        {
            if (headerModelo.getIdFornecedor() != 0)
            {
                if (!headerModelo.getTipoPagamento().equalsIgnoreCase("Seleccionar.."))
                {
                    if (!headerModelo.getMoeda().equalsIgnoreCase("Seleccionar..."))
                    {
                        if (headerModelo.getTaxaCambio() != 0)
                        {
                            if(!carrinhoCompras.isEmpty())
                            {
                            if (headerController.save(headerModelo))
                            {
                                int idActual = ControllerUtil.getIdActual("tbl_compra_header");

                                for (CompraItensModelo item : carrinhoCompras)
                                {
                                    item.setIdCompraHeader(idActual);

                                    if (controller.save(item))
                                    {
                                        stockModelo = stockController.getByCampo("id_produto", String.valueOf(item.getIdProduto()));

                                        if (stockModelo != null)
                                        {
                                            stockModelo.setQuantidade(stockModelo.getQuantidade() + item.getQuatidade());
                                            stockModelo.setCusto(item.getPreco() + item.getImposto());
                                            stockModelo.setValor(stockModelo.getQuantidade() * stockModelo.getCusto());
                                        }

                                        if (!stockController.update(stockModelo))
                                        {
                                            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "GCBoutique", "Erro N.º SG001: Ao Atualizar o Stock! Consulte o Suporte"));
                                        }

                                        //context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "GCBoutique", "Registo Guardado Com Sucesso!"));
                                    } else
                                    {
                                        context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "GCBoutique", "Erro N.º SG001: Ao Guardar o Registo(Item)! Consulte o Suporte"));
                                    }
                                }

                                if (headerModelo.getTipoPagamento().equalsIgnoreCase("prazo"))
                                {
                                    contasPagarModelo = new ContasPagarModelo();

                                    contasPagarModelo.setIdDocumento(headerModelo.getNumDoc());
                                    contasPagarModelo.setIdEntidade(headerModelo.getIdFornecedor());
                                    contasPagarModelo.setCredito(getTotalGeral());
                                    contasPagarModelo.setDebito(0);

                                    if (contasPagarController.save(contasPagarModelo))
                                    {
                                        carrinhoCompras = new ArrayList<CompraItensModelo>();
                                        headerModelo = new CompraHeaderModelo();
                                    } else
                                    {
                                        context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "GCBoutique", "Erro N.º SG001: Ao Guardar o Registo(Lançamento Contabil)! Consulte o Suporte"));
                                    }
                                }

                                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "GCBoutique", "Registo Guardado Com Sucesso!"));

                            } else
                            {
                                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "GCBoutique", "Erro N.º SG001: Ao Guardar o Registo(Header)! Consulte o Suporte"));
                            }
                        }else
                        {
                            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "GCBoutique", "Erro N.º SG001: Ao Guardar o Registo. Não Existem Itens no Doc.!"));
                        }
                        } else
                        {
                            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Informar a taxa de Câmbio"));
                        }
                    } else
                    {
                        context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Seleccionar a moeda"));
                    }
                } else
                {
                    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Seleccionar o tipo de pagamento"));
                }
            } else
            {
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Seleccionar o fornecedor!"));
            }
        } else
        {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Aviso N.º UG002: Deve Seleccionar a forma de pagamento!"));
        }

    }

    /**
     * Método que actualiza os dados do registo.
     * @param o evento gerado pela página.
     */
    public void actulizar(ActionEvent event)
    {
        context = FacesContext.getCurrentInstance();

        if (estornarItemsDoc())
        {
            for (CompraItensModelo item : carrinhoCompras)
            {
                item.setIdCompraHeader(headerModeloTemp.getId());

                if (controller.save(item))
                {
                    //carrinhoCompras = new ArrayList<CompraItensModelo>();
                    //headerModeloTemp = new CompraHeaderModelo();
                    //context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "GCBoutique", "Registo Actualizado Com Sucesso!"));
                } else
                {
                    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "GCBoutique", "Erro N.º SG001: Ao Actualizar o Registo(Item)! Consulte o Suporte"));
                }
            }
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "GCBoutique", "Registo Actualizado Com Sucesso!"));
        } else
        {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Erro N.º SG001: Ao Actualizar(Estornar doc)"));
        }
    }

    /**
     * Permite estornar itens de um determinado documento
     * @return verdadeiro se os itens do documento foram bem estornados e falso se não forem bem estornados
     */
    public boolean estornarItemsDoc()
    {
        boolean result = false;

        if (headerModeloTemp != null)
        {
            result = controller.eliminarPorCampo("tbl_compra_itens", "id_compra_header", String.valueOf(headerModeloTemp.getId()));
        }

        return result;
    }

    public boolean carrinhoComprasVaziu()
    {
        return this.carrinhoCompras.isEmpty();
    }

    /**
     * Método que elimina os dados do registo.
     * @param o evento gerado pela página.
     */
    public void eliminar(ActionEvent event)
    {
        context = FacesContext.getCurrentInstance();

        if (modeloTemp.getId() != 0)
        {
            if (controller.eliminar(modeloTemp.getId(), "tbl_compra_header"))
            {
                modeloTemp = new CompraItensModelo();
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "GCBoutique", "Registo Eliminado Com Sucesso!"));
            }

        } else
        {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "GCBoutique", "Erro Aviso N.º UE001: Deve Seleccionar um registo."));
        }
    }

    /**
     * Métodos que cria uma nova instância do objecto modelo.
     * @param event o e evento gerado.
     */
    public void novoModelo(ActionEvent event)
    {
        modeloTemp = new CompraItensModelo();
    }

    /**
     * Limpa todas as variaveis principais
     */
    public String limparRegistos()
    {
        this.modelo = new CompraItensModelo();
        this.modeloTemp = new CompraItensModelo();
        this.carrinhoCompras = new ArrayList<CompraItensModelo>();
        this.headerModelo = new CompraHeaderModelo();
        this.headerModeloTemp = new CompraHeaderModelo();

        return "/inicio.jsf";
    }
}
